#ifndef __BG_LUA_H__
#define __BG_LUA_H__

#include "../../lua/src/lauxlib.h"
#include "../../lua/src/lualib.h"

#define BIT_MASK(nBits) ((1<<(nBits))-1)

enum
{
	LSYSCALL_ERROR						= 1,	// (msg)
	LSYSCALL_MERGETABLEPASSIVE			= 2,	// (dest, src)
	LSYSCALL_MERGETABLEAGGRESSIVE		= 3,	// (dest, src)
	LSYSCALL_PARSEVECTOR3				= 4,	// (str)
	LSYSCALL_SETMETATABLE				= 5,	// (table, metatable)
	LSYSCALL_TRACE						= 6,	// (str)
	LSYSCALL_SPECIALPROPERTYVALUE		= 7,	// (catid, oid, spid[, constructor])
	LSYSCALL_SETSPECIALPROPERTY			= 8,	// (catid, oid, spid, value)
	LSYSCALL_RAWSET						= 9,	// (table, key, value)
	LSYSCALL_RAWGET						= 10,	// (table, key)
	LSYSCALL_TONUMBER					= 11,	// (v)
	LSYSCALL_OBJECTCLIENTID				= 12,	// (oid)
	LSYSCALL_NEXT						= 13,	// (table, key)
	LSYSCALL_CLONETABLE					= 14,	// (table, key)
	LSYSCALL_MERGETABLES				= 15,	// (destination, source)
	LSYSCALL_VALUEDESCRIPTION			= 16,	// (value)
	LSYSCALL_IRAND						= 17,	// (min, max)
	LSYSCALL_REPLICATEEVENT				= 18,	// (hookID, types, params, ...)
	LSYSCALL_ENUMERATETYPES				= 19,	// ()
	LSYSCALL_CREATEREPLICATIONTABLE		= 20,	// (prop)
	LSYSCALL_BREAK						= 21,	// ()
	LSYSCALL_GLOBALSTABLE				= 22,	// ()
	LSYSCALL_GDATAPROPERTYVALUE			= 23,	// (objid, gdid[, constructor])
	LSYSCALL_SETGDATAPROPERTY			= 24,	// (objid, gdid, v)
	LSYSCALL_VECTORKEY					= 25,	// (x, y, z)
	LSYSCALL_PRIMITIVETYPE				= 26,	// (v)

	LSYSCALL_LOCALE						= 27,	// ()

	LSYSCALL_DATATYPEINFO				= 28,	// (type)

	LSYSCALL_NEWNATIVEINSTANCE			= 29,	// (catid)

	LSYSCALL_DECODEEVENTID				= 30,	// (params)
	LSYSCALL_DECODEEVENTPARAMETERS		= 31,	// (params, paramTypes)
};

enum
{
	LFIELDTYPE_FLOAT,
	LFIELDTYPE_VECTOR3,
	LFIELDTYPE_BITFIELD,
	LFIELDTYPE_INTEGER,

	LFIELDTYPE_NOACCESS,

	LFIELDTYPE_SPECIAL,
};

// Rep table index offsets and masks
// (Max is 23 bits for SP floats)
enum
{
	// 64 slots (6 bits)
	LREPTABLE_SLOT_OFFSET	= 0,
	LREPTABLE_SLOT_BITS		= 6,

	// 1 bit for stat flag
	LREPTABLE_STAT_OFFSET	= 6,
	LREPTABLE_STAT_BITS		= 1,

	// 5 bits for bit offset
	LREPTABLE_BITOFFS_OFFSET	= 7,
	LREPTABLE_BITOFFS_BITS		= 5,

	// 4 bits for type
	LREPTABLE_TYPE_OFFSET	= 11,
	LREPTABLE_TYPE_BITS		= 4,
};

enum
{
	LCACHEID_CLIENTCLASS,
};

typedef struct
{
	const char *name;
	int eFieldOffset;	// Field offset for non-player entities
	int pFieldOffset;	// Field offset for player entities, -1 = doesn't have a player state version
	int readHandlingType;
	int writeHandlingType;
	const char *className;

	int bitMask;
} bg_luaSpecialProperty_t;

typedef struct
{
	const char *name;
	const bg_luaSpecialProperty_t *specialProperties;
	int numSpecialProperties;
	int (*readProperty) (struct lua_State *L, int oid, const bg_luaSpecialProperty_t *prop);
	int (*writeProperty) (struct lua_State *L, int oid, const bg_luaSpecialProperty_t *prop, int valueIndex);
} bg_luaSystemClass_t;

int BG_LuaSysCall(struct lua_State *L, int callID);
int BG_LuaReadSpecialProperty(struct lua_State *L, const void *object, const bg_luaSpecialProperty_t *p, int offset);
int BG_LuaWriteSpecialProperty(struct lua_State *L, int valueIdx, void *object, const bg_luaSpecialProperty_t *p, int offset);
int BG_LuaEnumerateTypes(struct lua_State *L);
int BG_LuaCreateReplicationTable(struct lua_State *L);
int BG_LuaGDataPropertyValue(struct lua_State *L, data32u_t *gdata, int *stats);
int BG_LuaSetGDataProperty(struct lua_State *L, data32u_t *gdata, int *stats);
void BG_PushTableFromInfo(struct lua_State *L, const char *info);
void BG_LuaBuildEventCommand(struct lua_State *L, char *result, int limit);

void BG_PushVector3(struct lua_State *L, float x, float y, float z);
void BG_PushVector3v(struct lua_State *L, const float *v);

void BG_GetVector3v(lua_State *L, int index, float *v);

int BG_LuaSpecialPropertyValue(struct lua_State *L, const bg_luaSystemClass_t *classes, int numClasses);
int BG_LuaSetSpecialProperty(struct lua_State *L, const bg_luaSystemClass_t *classes, int numClasses);
void BG_LuaLoadStandardLibraries(struct lua_State *L);
void BG_LuaRegisterClasses(struct lua_State *L, const bg_luaSystemClass_t *classes, int numClasses);
void BG_LuaRegisterTypes(struct lua_State *L);

int BG_LuaDecodeEventID(lua_State *L);
int BG_LuaDecodeEventParameters(lua_State *L);

#endif
